<template>
    <view class="draggable-list" :style="listStyle">
        <view
            v-for="(item, index) in localList"
            :key="item.id"
            class="draggable-item"
            :style="getItemStyle(index)"
        >
            <view class="item-content">
                <view class="item-main" @click="tapItem(item)">
                    <template>
                        <image
                            :src="item.image"
                            class="item-image"
                            mode="aspectFit"
                        />
                    </template>
                </view>
                <view class="right-area">
                    <view
                        class="drag-handle"
                        @touchstart.stop="touchStart($event, index)"
                        @touchmove.stop="touchMove"
                        @touchend.stop="touchEnd"
                    >
                        <image
                            class="drag-icon"
                            src="https://cos.aitshirt.cn/app-icon/%E5%88%87%E6%8D%A2%E9%A1%BA%E5%BA%8F%402x.png"
                        ></image>
                    </view>
                </view>
            </view>
        </view>
    </view>
  <div class="mark-body" style="" @click="close"></div>
</template>

<script>
import { cloneDeep } from 'lodash';

export default {
    name: 'DraggableList',
    data() {
        return {
            list: [],
            localList: [],
            dragIndex: -1,
            startY: 0,
            currentY: 0,
            isDragging: false,
            itemHeight: 0,
            listHeight: 0,
            moveList: [],
            listTop: 0,
            lastToIndex: -1,
            lastMovingDirection: null,
        };
    },
    computed: {
        listStyle() {
            return {
                height: `${this.listHeight}px`,
            };
        },
    },
    watch: {
        list: {
            immediate: true,
            handler(newVal) {
                this.localList = JSON.parse(JSON.stringify(newVal)).reverse();
                this.$nextTick(() => {
                    this.initMoveList();
                });
            },
        },
    },
    mounted() {
        // this.$nextTick(() => {
        //   this.initMeasurements()
        // })
    },
    methods: {
      tapItem(item) {
        this.$emit('tapItem', item);
      },
      close() {
        // console.log('close ->>>>>>>>>>>>>>>>>>>')
        this.$emit('close');
      },
        open(newList) {
            this.list = cloneDeep(newList).map((node) => {
                const offScreenImg = node.getOffScreenCanvasImage();
                return Object.freeze({id: node.__id__, image: offScreenImg });
            });
            this.$nextTick(() => {
                this.initMeasurements();
            });
        },

        initMoveList() {
            this.moveList = this.localList.map((_, index) => ({
                y: index * this.itemHeight,
                moving: false,
            }));
            this.listHeight = this.itemHeight * this.localList.length;
        },

        initMeasurements() {
            const query = uni.createSelectorQuery().in(this);
            query
                .select('.draggable-list')
                .boundingClientRect((data) => {
                    if (data) {
                        this.listTop = data.top;
                    }
                })
                .exec();

            query
                .select('.draggable-item')
                .boundingClientRect((data) => {
                    if (data) {
                        this.itemHeight = data.height;
                        this.initMoveList();
                    }
                })
                .exec();
        },

        touchStart(e, index) {
            this.isDragging = true;
            this.dragIndex = index;
            this.startY = e.touches[0].clientY - this.moveList[index].y;
            this.currentY = this.moveList[index].y;
            this.moveList[index].moving = true;
        },

        touchMove(e) {
            if (!this.isDragging) return;

            const touchY = e.touches[0].clientY - this.listTop;

            // 保存上一次的位置用于判断方向
            const previousY = this.currentY;

            // 限制拖动范围在列表内
            this.currentY = Math.max(
                0,
                Math.min(
                    touchY - this.startY + this.listTop,
                    this.listHeight - this.itemHeight,
                ),
            );

            const rawTargetIndex = this.currentY / this.itemHeight;
            const targetIndex = Math.round(rawTargetIndex);

            if (
                targetIndex >= 0 &&
                targetIndex < this.localList.length &&
                targetIndex !== this.dragIndex &&
                Math.abs(rawTargetIndex - targetIndex) < 0.5
            ) {
                // 检测拖动方向变化
                const movingDirection =
                    this.currentY - previousY > 0 ? 'down' : 'up';

                // 移除方向改变时重置所有元素状态的逻辑
                this.lastMovingDirection = movingDirection;

                this.updateItemsPosition(this.dragIndex, targetIndex);
            }
        },

        touchEnd() {
            if (!this.isDragging) return;

            const rawTargetIndex = this.currentY / this.itemHeight;
            const floorIndex = Math.floor(rawTargetIndex);
            const offsetPercentage = rawTargetIndex - floorIndex;

            let finalIndex;
            if (offsetPercentage > 0.5) {
                finalIndex = floorIndex + 1;
            } else {
                finalIndex = floorIndex;
            }

            finalIndex = Math.max(
                0,
                Math.min(finalIndex, this.localList.length - 1),
            );

            if (finalIndex !== this.dragIndex) {
                const item = this.localList.splice(this.dragIndex, 1)[0];
                this.localList.splice(finalIndex, 0, item);
                this.$emit('update', [...this.localList].reverse());
            }

            // 完全重置所有元素的状态
            this.moveList = this.localList.map((_, index) => ({
                y: index * this.itemHeight,
                moving: false,
                animating: false, // 确保动画状态也被重置
            }));

            // 重置所有状态变量
            this.isDragging = false;
            this.dragIndex = -1;
            this.currentY = 0;
            this.lastToIndex = -1;
            this.lastMovingDirection = null;
            this.startY = 0; // 重置起始位置

            // 使用 nextTick 确保视图更新后重新初始化
            this.$nextTick(() => {
                // 重新初始化移动列表
                this.initMoveList();
            });
        },

        updateItemsPosition(fromIndex, toIndex) {
            if (this.lastToIndex === toIndex) return;

            const previousToIndex = this.lastToIndex;
            this.lastToIndex = toIndex;

            const positions = this.moveList.map((item, index) => {
                // 被拖动的元素
                if (index === fromIndex) {
                    return {
                        ...item,
                        y: this.currentY,
                        moving: true,
                        animating: false,
                    };
                }

                let newY = index * this.itemHeight;
                let shouldAnimate = false;

                // 确定哪些元素需要移动
                if (fromIndex < toIndex) {
                    if (index > fromIndex && index <= toIndex) {
                        newY = (index - 1) * this.itemHeight;
                        shouldAnimate = true;
                    }
                } else if (fromIndex > toIndex) {
                    if (index >= toIndex && index < fromIndex) {
                        newY = (index + 1) * this.itemHeight;
                        shouldAnimate = true;
                    }
                }

                // 保持现有的动画状态，只在位置真正改变时更新
                const currentPosition = this.moveList[index];
                const positionChanged = currentPosition.y !== newY;

                return {
                    ...item,
                    y: newY,
                    moving: false,
                    animating: positionChanged,
                };
            });

            this.moveList = positions;
        },

        getItemStyle(index) {
            const moveData = this.moveList[index];
            const isDraggingItem = index === this.dragIndex;

            return {
                transform: `translateY(${isDraggingItem ? this.currentY : moveData?.y}px)`,
                transition: moveData?.moving ? 'none' : 'transform 0.3s ease',
                zIndex: isDraggingItem ? 2 : 1,
                boxShadow: isDraggingItem
                    ? '0 2px 10px rgba(0,0,0,0.1)'
                    : 'none',
                pointerEvents: 'auto', // 确保所有元素都可以接收事件
            };
        },
    },
};
</script>

<style scoped lang="scss">
.mark-body{
  position: absolute;
  left: 0;
  top: 0;
  z-index: 9;
  width: 100vw;
  height: 100vh;
}
.draggable-list {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 16rpx;
  right: 120rpx;
  bottom: 36rpx;
  width: 200rpx;
  min-height: 600rpx;
  max-height: 600rpx;
  overflow: auto;
  background: rgba(34, 34, 34, 0.6);
  border-radius: 16rpx;
  padding: 20rpx;
  box-sizing: border-box;
  z-index: 10;
}

.draggable-item {
    padding: 20rpx;
    position: absolute;
    width: 100%;
    left: 0;
    box-sizing: border-box;
    will-change: transform;
    border-bottom: 2rpx solid #eeeeee;
}

.item-content {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.item-main {
    display: flex;
    align-items: center;
    width: 72rpx;
    height: 72rpx;
    background: #ffffff;
    border: 2rpx solid #707070;
    .item-image {
        width: 72rpx;
        height: 72rpx;
    }
}

.item-icon {
    width: 40rpx;
    height: 40rpx;
    margin-right: 20rpx;
}

.item-text {
    font-size: 28rpx;
}

.drag-handle {
    padding: 0 20rpx;
    cursor: move;
}

.drag-icon {
    width: 32rpx;
    height: 32rpx;
}
</style>
